package ro.ubbcluj.cs.damate.services;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ro.ubbcluj.cs.damate.persistence.entities.Token;
import ro.ubbcluj.cs.damate.persistence.entities.User;
import ro.ubbcluj.cs.damate.persistence.repository.TokenRepository;
import ro.ubbcluj.cs.damate.utils.EntityUtils;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author Lóránd Fazakas (lorand)
 *         Date: 6/26/13
 *         Time: 0:10 PM
 */
@Service
public class TokenService {

    @Autowired
    private TokenRepository tokenRepository;

    public Token createNewToken(User user, String ipAddress) {
        Token token = new Token();
        token.setUser(user);
        token.setIpAddress(ipAddress);
        token.setExpiration(new Timestamp(createExpirationDateFromNow()));
        token.setToken(EntityUtils.generateUUID(new String[]{user.getUsername(), ipAddress, token.getExpiration().toString()}));
        create(token);
        return token;
    }

    private long createExpirationDateFromNow() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTimeInMillis();
    }

    @Transactional
    public void create(Token transientToken) {
        tokenRepository.save(transientToken);
    }

    @Transactional
    public void delete(Token persistentToken) {
        tokenRepository.delete(persistentToken);
    }

    public Token findByToken(String tokenKey) {
        if (StringUtils.isNotEmpty(tokenKey)) {
            List<Token> tokens = tokenRepository.findByToken(tokenKey);
            if (tokens != null && !tokens.isEmpty()) {
                return tokens.get(0);
            }
        }
        return null;
    }

    public List<Token> findByUser(User user) {
        if (user != null) {
            return tokenRepository.findByUserAndExpirationGreaterThan(user, new Timestamp(new Date().getTime()));
        }
        return null;
    }

    public boolean isExpiredToken(String tokenKey) {
        Token token = findByToken(tokenKey);
        if (token != null) {
            return !token.getExpiration().after(new Date());
        }
        return false;
    }

    public boolean isValidToken(String tokenKey, String ipAddress) {
        Token token = findByToken(tokenKey);
        if (token != null && token.getExpiration().after(new Date()) && token.getIpAddress().equals(ipAddress)) {
            return true;
        }
        return false;
    }

    public User findUserByToken(String tokenKey) {
        Token token = findByToken(tokenKey);
        return token != null ? token.getUser() : null;
    }
}
